package net.pushtime.dicmonitor.service.impl;

import net.pushtime.dicmonitor.config.ApplicationProperties;
import net.pushtime.dicmonitor.service.DictionaryMonitorService;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DictionaryMonitorServiceImpl implements DictionaryMonitorService {

    // 用户配置需要监控的目录列表
    private final List<String> paths;

    private final long interval;

    private final FileAlterationListenerAdaptor fileAlterationListenerAdaptor;

    private final Map<String, FileAlterationMonitor> monitors;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    public DictionaryMonitorServiceImpl(ApplicationProperties properties,
                                        FileAlterationListenerAdaptor fileAlterationListenerAdaptor) {
        this.fileAlterationListenerAdaptor = fileAlterationListenerAdaptor;
        this.paths = properties.getMonitor().getPaths();
        this.interval = properties.getMonitor().getInterval();
        this.monitors = new HashMap<>();
    }


    /**
     * 初始化监控程序
     */
    @Override
    public void init() {
        logger.debug("init monitor program with paths: {}", paths);
        paths.forEach(path -> {
            // 这里可以使用filter参数 FileAlterationObserver(path, filter) 对监控对文件进行过滤
            FileAlterationObserver observer = new FileAlterationObserver(path);
            observer.addListener(fileAlterationListenerAdaptor);
            FileAlterationMonitor fileAlterationMonitor =  new FileAlterationMonitor(interval);
            fileAlterationMonitor.addObserver(observer);
            // 将监控程序添加到列表，方便管理
            monitors.put(path, fileAlterationMonitor);
        });
    }

    /**
     * 开始目录监控
     * 在配置application.monitor.paths 中加入需要监控的目录，随后重写此方法，
     * 即可完成监控
     */
    @Override
    public void startMonitor() {
        logger.debug("start to monitor paths {}", paths);
        monitors.forEach((path, monitor) -> {
            try {
                monitor.start();
            } catch (Exception e) {
                logger.error("Failed to start monitor path {}, cause by {}", path, e.getMessage());
            }
        });
    }

    @Override
    public void close() {
        monitors.forEach((path, monitor) -> {
            try {
                monitor.stop();
            } catch (Exception e) {
                logger.error("Failed to stop monitor path {}, cause by {}", path, e.getMessage());
            }
        });
    }
}
